package com.fanqj.sentinel.controller;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import org.apache.tomcat.jni.Time;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 流量控制demo
 * @author <a href="mailto:fanqijin@wxchina.com">fanqj</a>
 * @Date 2021年02月01日 17:14
 * @Version 6.4.1
 */
@RestController
@RequestMapping("/flow")
public class FlowController {

    final Logger logger = LoggerFactory.getLogger(FlowController.class);

    @GetMapping("/thread")
    public String threadCountFlow() {
        try (Entry threadEntry = SphU.entry("threadFlowRule")) {
            TimeUnit.MILLISECONDS.sleep(1000);
            return "Success pass threadFlow!";
        } catch (BlockException e) {
            logger.error(e.getMessage());
            return "Block by threadFlow";
        } catch (InterruptedException e) {
            logger.error(e.getMessage());
            return "Error by threadFlow";
        }
    }

    @GetMapping("/qps")
    @SentinelResource(value = "qpsFlowRule", blockHandler = "qpsFlowBlock", fallback = "qpsFlowFallBack")
    public String qpsFlow() {
        return "Success pass qpsFlow!";
    }

    public String qpsFlowBlock(BlockException blockException) {
        logger.error(blockException.getMessage());
        return "Block by qpsFlow!";
    }

    public String qpsFlowFallBack(Throwable throwable) {
        logger.error(throwable.getMessage());
        return "FallBack by qpsFlow!";
    }

    @PostConstruct
    public void initFlowRule() {
        List<FlowRule> rules = new ArrayList<FlowRule>();
        FlowRule threadFlowRule = new FlowRule();
        threadFlowRule.setResource("threadFlowRule");
        threadFlowRule.setCount(1);
        threadFlowRule.setGrade(RuleConstant.FLOW_GRADE_THREAD);
        rules.add(threadFlowRule);

        FlowRule qpsFlowRule = new FlowRule();
        qpsFlowRule.setResource("qpsFlowRule");
        qpsFlowRule.setCount(1);
        qpsFlowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rules.add(qpsFlowRule);

        FlowRuleManager.loadRules(rules);
    }

}
